package org.kth.dks.test_bed;

import org.kth.dks.DKSObject;
import org.kth.dks.dks_comm.ConnectionManager;
import org.kth.dks.dks_comm.DKSOverlayAddress;
import org.kth.dks.dks_comm.DKSRef;
import org.kth.dks.dks_dht.DKSDHTImpl;

/**
 * <p>Title: DKS Hello World Application</p>
 * <p>Description: DKS Middleware</p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: KTH-IMIT/SICS</p>
 * @author Ali Ghodsi
 * @version 1.0
 */

public class Client {

  /**
   * Local port number DKS will run on
   */
  private long START_PORT = 4441;

  /**
   * Logical DKS identifier to be used for the first node
   */
  private long START_IDENTIFIER = 0;

  public static void main(String[] args) {
    System.out.println("Starting DKS");

    Client helloApp = new Client();

    helloApp.run(args);
  }

  /**
   * Creates two DKS nodes, adds a hello world string through one node and retrieves it from the other
   */
  void run(String[] args) {

   if (args.length!=3) {
     System.err.println("Syntax:\nClient PORTNUMBER IDENTIFIER EXISTINGDKSURL\n");
     System.exit(0);
   }

   START_PORT = Integer.parseInt(args[0]);
   START_IDENTIFIER = Integer.parseInt(args[1]);
   String EXISTING = args[2];

    ConnectionManager cm = null;

    // DKSObject is a wrapper around a byte array, we store our value "Hello World!"
    // as a byte array inside it.
    DKSObject helloValue  = new DKSObject("Hello DHT".getBytes());
    DKSObject helloValue2 = new DKSObject("Hello2 DHT".getBytes());

    System.out.println("*** NODE 0 KEY 1 ITEM INSERTED ***");

    DKSDHTImpl secondNode = null;
    try {
      cm = ConnectionManager.getInstance( (int) START_PORT); // Static factory only used for testing, should use getInstance (singleton)
      // The following starts a second node with identifier START_IDENTIFIER+1
      // and connects it to the first node created

      // Format of DKSOverlayAddresses : dksoverlay://[GroupId]/[NodeId]/[NodeGUID] (NodeId's must be unique)
      DKSOverlayAddress secondNodeId = new DKSOverlayAddress("dksoverlay://0/" +
          (START_IDENTIFIER) + "/0");
      secondNode = new DKSDHTImpl(cm, secondNodeId);

      DKSRef bootStrapNode = DKSRef.valueOf(EXISTING); // create a reference to the first node

      secondNode.join(bootStrapNode);
      System.out.println("Second node created with DKSURL " +
                         secondNode.getDKSURL());

      secondNode.addToBinding(1234, helloValue);
      secondNode.addToBinding(1234, helloValue2);

      DKSObject[] res = secondNode.lookupBinding(1234);

      for (int x = 0; x<res.length; x++) {
        System.out.println(res[x]);
      }

      System.out.println(res.length);


    }
    catch (Exception ex) {
      ex.printStackTrace();
    }

    sleep(500);
    secondNode.leave();

    sleep(500);
    cm.end(); // Closes down all the sockets and threads
    System.out.println("Done.");

  }

  /**
   * Sleeps for some milliseconds
   * @param msec is the number of milliseconds
   */

  static void sleep(long msec) {
    try {
      Thread.sleep(msec);
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
  }

}
